﻿using System;
using System.Diagnostics;
using CommandRunner.Model;

namespace CommandRunner
{
    public class ProcessCommand
    {
        public event CommandProcessedDelegate CommandFinished;

        private Process process;
        private CommandResult commandResult;
        private string stdOutput;
        private string stdError;

        public ProcessCommand(CommandResult cmdResult)
        {
            commandResult = cmdResult;
            process = new Process();
            PrepareCommand();
        }

        public void RunCommand()
        {
            commandResult.Status = CommandExecutionStatus.Executing;
            process.Start();

            if (!commandResult.Command.InteractiveWindow)
            {
                process.BeginOutputReadLine();
                process.BeginErrorReadLine();
            }
        }

        private void PrepareCommand()
        {
            stdOutput = "Std Out:" + System.Environment.NewLine;
            stdError = "Std Err:" + System.Environment.NewLine;
            process.EnableRaisingEvents = true;
            process.StartInfo.UseShellExecute = false;
            process.Exited += delegate { CommandFinishedRunning(commandResult, process); };
            process.StartInfo.FileName = "cmd.exe";
            process.StartInfo.Arguments = "/C " + commandResult.Command.Execute as String;
            if (!String.IsNullOrEmpty(commandResult.Command.WorkingDirectory))
                process.StartInfo.WorkingDirectory = commandResult.Command.WorkingDirectory;

            if (commandResult.Command.InteractiveWindow)
            {
                process.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
                process.StartInfo.CreateNoWindow = false;
                process.StartInfo.RedirectStandardOutput = false;
                process.StartInfo.RedirectStandardError = false;
            }
            else
            {
                process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                process.StartInfo.CreateNoWindow = true;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError = true;
                process.OutputDataReceived += new DataReceivedEventHandler(StandardOutputHandler);
                process.ErrorDataReceived += new DataReceivedEventHandler(StandardErrorHandler);
            }
        }

        private void CommandFinishedRunning(CommandResult commandResult, Process cmd)
        {
            if (!commandResult.Command.InteractiveWindow)
                commandResult.Output = stdOutput + stdError;
            else
                commandResult.Output = "Interactive process";

            if (cmd.ExitCode != 0)
                commandResult.Status = CommandExecutionStatus.Failure;
            else
                commandResult.Status = CommandExecutionStatus.Success;

            if (CommandFinished != null)
                CommandFinished(commandResult);
        }

        private void StandardOutputHandler(object sender, DataReceivedEventArgs line)
        {
            stdOutput += line.Data + System.Environment.NewLine;
        }

        private void StandardErrorHandler(object sender, DataReceivedEventArgs line)
        {
            stdError += line.Data + System.Environment.NewLine;
        }
    }
}
